#include "sqlite.h"
#include "log/Logger.h"
#include "common/Semaphore.h"
#include <vector>
#include <string>

//设备记录表
char  *createDeviceInfoTbl = "CREATE TABLE DeviceInfo("  \
"runtime                      CHAR(50)    NOT NULL," \
"currenttime    CHAR(50) );";

char *checkTableSql = "tables";

static CSemaphore* g_CQSLiteSep;
static std::vector< std::string > g_vecSQLiteRet;

static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
   int i;
   g_vecSQLiteRet.clear();
   for(i= 0; i <argc; i++)
   {
       printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
       g_vecSQLiteRet.push_back(std::string(argv[i]));
   } 
   printf("\n");
   g_CQSLiteSep->Signal();
   return 0;
}

CSqLite::CSqLite(std::string strDBFile)
{
    const char *s= sqlite3_libversion();
    LOG_INFO("sqlite3_libversion : " << std::string(s));
    m_strDB = strDBFile;
}

CSqLite::~CSqLite()
{
    ;
}

bool CSqLite::open()
{
    char *zErrMsg = 0;
    int nRet = sqlite3_open(m_strDB.c_str(), &m_phandle);
    if (SQLITE_OK != nRet)
    {
        fprintf(stderr, "Can't Open database:%s\n", sqlite3_errmsg(m_phandle));
        sqlite3_close(m_phandle);
        return false;
    }
    LOG_INFO("Opened database successfully");
    if ( !CreatTable())
    {
        LOG_INFO("create table error");
        return false;
    }
    return true;
}
bool CSqLite::getAllTable(std::set<std::string>& setTable)
{
    char *zErrMsg=0;
    sqlite3_stmt* stmt2= NULL;
    std::string strSql = "SELECT name FROM sqlite_master WHERE type='table'";
    if (sqlite3_prepare_v2(m_phandle, strSql.c_str(), strSql.size(), &stmt2, NULL)!=SQLITE_OK)
    {
        if(nullptr !=stmt2)
        {
            sqlite3_finalize(stmt2);
        }
        sqlite3_close(m_phandle);
        return false;
    }
    int i = 0;
    while (sqlite3_step(stmt2) == SQLITE_ROW)
    {
        std::string table = (const char *) sqlite3_column_text(stmt2,0);
        setTable.insert(table);
        LOG_INFO("find tables:" << table);
    }
    return true;
}

bool CSqLite::CreatTable()
{
    char *zErrMsg = 0;
    std::set<std::string> setTabl;
    if(!getAllTable(setTabl))
    {
        LOG_INFO("getAllTable error");
        return false;
    }
    if (setTabl.end() == setTabl.find("DeviceInfo"))
    {
        int res = sqlite3_exec(m_phandle, createDeviceInfoTbl, nullptr, nullptr, &zErrMsg);
        if (res)
        {
            LOG_INFO("SQL error:" << zErrMsg);
            sqlite3_free(zErrMsg);
        }
        else 
        {
            LOG_INFO("Table created successfully");
        }
    }
}

bool CSqLite::close()
{
    int nRet = sqlite3_close(m_phandle);
    if(0 !=nRet)
    {
        fprintf(stderr, "Can't close database:%s\n", sqlite3_errmsg(m_phandle));
        return false;
    }
    LOG_INFO("close database successfully");
    return true;
}

bool CSqLite::writeDB(std::string & strSql)
{
    char *zErrMsg = 0;
    int res = sqlite3_exec(m_phandle, strSql.c_str(), nullptr, nullptr, &zErrMsg);
    if (res != SQLITE_OK)
    {
        fprintf(stderr, "SQL error :%s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return false;
    }
    else 
    {
        LOG_INFO("write data successfully");
    }
    return true;
}
bool CSqLite::readDB(std::string &strSql, Json::Value &ReadResult)
{
    char *zErrMsg = 0;
    sqlite3_stmt *stmt2 = nullptr;
    if(sqlite3_prepare_v2(m_phandle, strSql.c_str() ,strSql.size(), &stmt2, nullptr) != SQLITE_OK)
    {
        if(nullptr !=stmt2)
        {
            sqlite3_finalize(stmt2);    
        }
        sqlite3_close(m_phandle);
        return false;
    }
    int fileCount = sqlite3_column_count(stmt2);
    LOG_INFO("The column count is " << fileCount);
    while(sqlite3_step(stmt2)==SQLITE_ROW)
    {
        std::string runtime = (const char*) sqlite3_column_text(stmt2,0);	
        std::string currentTime = (const char*)sqlite3_column_text(stmt2,1);
        Json::Value temp = Json::nullValue;
        temp["runtime"] = runtime;
        temp["currenttime"] = runtime;
        ReadResult.append(temp);
    }
    return true;
}